"""
四川麻将游戏模拟器
"""
import random
from typing import List, Tuple, Dict, Optional
from sichuanmajiang.engine.cards import Tile, TileSet, create_standard_mahjong_set
from sichuanmajiang.engine.rules import check_hu, check_peng, check_gang, check_chi, calculate_score, calculate_fan


class Player:
    """麻将玩家"""
    def __init__(self, name: str, is_ai: bool = False):
        self.name = name
        self.hand = TileSet()  # 手牌
        self.exposed_tiles = []  # 副露牌（碰、杠的牌）
        self.discarded_tiles = TileSet()  # 打出的牌
        self.is_ai = is_ai
        self.score = 0
        self.is_turn = False
    
    def add_tile(self, tile: Tile):
        """摸牌"""
        self.hand.add(tile)
    
    def discard_tile(self, tile: Tile) -> bool:
        """打牌"""
        if self.hand.remove(tile):
            self.discarded_tiles.add(tile)
            return True
        return False
    
    def show_hand(self) -> str:
        """显示手牌"""
        return self.hand.to_string()
    
    def __str__(self):
        return self.name


class MahjongGame:
    """麻将游戏类"""
    def __init__(self, players: List[Player]):
        self.players = players
        self.wall = create_standard_mahjong_set()  # 牌墙
        self.discard_pile = TileSet()  # 弃牌堆
        self.current_player_index = 0
        self.is_game_over = False
        self.winner = None
        self.last_discarded_tile = None
        self.last_discarded_by = None
    
    def initialize_game(self):
        """初始化游戏"""
        # 洗牌
        random.shuffle(self.wall)
        
        # 发牌（每个玩家初始13张牌）
        for _ in range(13):
            for player in self.players:
                if self.wall:
                    player.add_tile(self.wall.pop())
        
        # 第一个玩家再摸一张牌
        self.players[0].add_tile(self.wall.pop())
        self.players[0].is_turn = True
    
    def next_turn(self):
        """切换到下一个玩家的回合"""
        # 重置当前玩家状态
        self.players[self.current_player_index].is_turn = False
        
        # 计算下一个玩家索引
        self.current_player_index = (self.current_player_index + 1) % len(self.players)
        
        # 设置下一个玩家的状态
        self.players[self.current_player_index].is_turn = True
    
    def player_draw(self, player_index: int) -> Optional[Tile]:
        """玩家摸牌"""
        if not self.wall:
            return None
        
        tile = self.wall.pop()
        self.players[player_index].add_tile(tile)
        return tile
    
    def player_discard(self, player_index: int, tile: Tile) -> bool:
        """玩家打牌"""
        player = self.players[player_index]
        if player.discard_tile(tile):
            self.discard_pile.add(tile)
            self.last_discarded_tile = tile
            self.last_discarded_by = player_index
            return True
        return False
    
    def check_player_actions(self, player_index: int, tile: Tile) -> Dict[str, bool]:
        """检查玩家可以执行的操作"""
        player = self.players[player_index]
        actions = {
            "can_hu": False,
            "can_peng": False,
            "can_gang": False,
            "can_chi": False
        }
        
        # 检查胡牌
        temp_hand = player.hand.tiles.copy()
        temp_hand.append(tile)
        actions["can_hu"] = check_hu(temp_hand)
        
        # 检查碰牌
        actions["can_peng"] = check_peng(tile, player.hand.tiles)
        
        # 检查杠牌
        can_gang, _ = check_gang(tile, player.hand.tiles, player.exposed_tiles)
        actions["can_gang"] = can_gang
        
        # 检查吃牌（只能吃上家的牌）
        previous_player_index = (self.current_player_index - 1) % len(self.players)
        if player_index != previous_player_index and self.last_discarded_by == previous_player_index:
            from sichuanmajiang.engine.rules import check_chi
            possible_chis = check_chi(tile, player.hand.tiles)
            actions["can_chi"] = len(possible_chis) > 0
        
        return actions
    
    def process_player_action(self, player_index: int, action: str, **kwargs) -> bool:
        """处理玩家操作"""
        player = self.players[player_index]
        
        if action == "discard":
            # 打牌操作
            tile = kwargs.get("tile")
            if self.player_discard(player_index, tile):
                # 检查其他玩家是否有反应
                for i in range(len(self.players)):
                    if i != player_index:
                        actions = self.check_player_actions(i, tile)
                        if actions["can_hu"]:
                            # 有玩家可以胡牌
                            self.handle_hu(i, "点炮")
                            return True
                        # 这里可以添加碰、杠、吃的处理逻辑
                
                # 如果没有玩家反应，轮到下一个玩家
                self.next_turn()
                return True
        
        elif action == "hu":
            # 胡牌操作
            hu_type = kwargs.get("hu_type", "自摸")
            return self.handle_hu(player_index, hu_type)
        
        elif action == "peng":
            # 碰牌操作
            tile = self.last_discarded_tile
            if tile and check_peng(tile, player.hand.tiles):
                # 从手牌中移除两张相同的牌
                for _ in range(2):
                    player.hand.remove(tile)
                # 添加到副露牌
                player.exposed_tiles.append([tile, tile, tile])  # 碰的牌显示为三张
                # 轮到碰牌的玩家出牌
                self.current_player_index = player_index
                for p in self.players:
                    p.is_turn = False
                player.is_turn = True
                return True
        
        elif action == "gang":
            # 杠牌操作
            tile = kwargs.get("tile", self.last_discarded_tile)
            can_gang, gang_type = check_gang(tile, player.hand.tiles, player.exposed_tiles)
            
            if can_gang:
                if gang_type == "暗杠":
                    # 从手牌中移除四张相同的牌
                    for _ in range(4):
                        player.hand.remove(tile)
                    player.exposed_tiles.append([tile, tile, tile, tile])
                    # 摸一张牌
                    self.player_draw(player_index)
                elif gang_type == "明杠":
                    # 从手牌中移除三张相同的牌
                    for _ in range(3):
                        player.hand.remove(tile)
                    player.exposed_tiles.append([tile, tile, tile, tile])
                    # 摸一张牌
                    self.player_draw(player_index)
                elif gang_type == "加杠":
                    # 找到对应的碰的牌组
                    for i, group in enumerate(player.exposed_tiles):
                        if len(group) == 3 and group[0] == tile:
                            # 从手牌中移除一张牌
                            player.hand.remove(tile)
                            # 将碰的牌组改为杠的牌组
                            player.exposed_tiles[i] = [tile, tile, tile, tile]
                            # 摸一张牌
                            self.player_draw(player_index)
                            break
                return True
        
        elif action == "chi":
            # 吃牌操作
            tile = self.last_discarded_tile
            from sichuanmajiang.engine.rules import check_chi
            possible_chis = check_chi(tile, player.hand.tiles)
            
            if possible_chis:
                # 选择第一个可能的顺子
                chi_tiles = possible_chis[0]
                # 从手牌中移除对应的牌
                for t in chi_tiles[:2]:  # 除了刚打出的那张牌
                    if t != tile:
                        player.hand.remove(t)
                # 添加到副露牌
                player.exposed_tiles.append(chi_tiles)
                # 轮到吃牌的玩家出牌
                self.current_player_index = player_index
                for p in self.players:
                    p.is_turn = False
                player.is_turn = True
                return True
        
        return False
    
    def handle_hu(self, player_index: int, hu_type: str) -> bool:
        """处理胡牌"""
        player = self.players[player_index]
        
        # 计算番数
        fan_count = calculate_fan(
            player.hand.tiles, 
            player.exposed_tiles, 
            self.last_discarded_tile
        )
        
        # 计算分数
        score = calculate_score(hu_type, fan_count)
        
        # 更新玩家分数
        player.score += score
        
        # 设置游戏结束
        self.is_game_over = True
        self.winner = player
        
        return True
    
    def get_current_state(self) -> Dict:
        """获取当前游戏状态"""
        return {
            "current_player": self.players[self.current_player_index].name,
            "players": [
                {
                    "name": p.name,
                    "hand_count": len(p.hand),
                    "exposed_tiles": p.exposed_tiles,
                    "score": p.score
                }
                for p in self.players
            ],
            "last_discarded_tile": self.last_discarded_tile,
            "wall_count": len(self.wall),
            "is_game_over": self.is_game_over,
            "winner": self.winner.name if self.winner else None
        }


class AIPlayer(Player):
    """AI玩家基类"""
    def __init__(self, name: str):
        super().__init__(name, is_ai=True)
    
    def decide_action(self, game_state: Dict) -> Tuple[str, Dict]:
        """
        决定下一步操作
        返回 (action_type, action_params)
        """
        # 这里将由具体的AI模型实现
        # 默认行为：随机打出一张牌
        if self.hand.tiles:
            # 简单规则：尝试胡牌
            if game_state.get("last_discarded_tile"):
                temp_hand = self.hand.tiles.copy()
                temp_hand.append(game_state["last_discarded_tile"])
                if check_hu(temp_hand):
                    return "hu", {"hu_type": "点炮"}
            
            # 随机选一张牌打出
            tile_to_discard = random.choice(self.hand.tiles)
            return "discard", {"tile": tile_to_discard}
        
        return "pass", {}


def run_game_example():
    """运行一个游戏示例"""
    # 创建玩家
    players = [
        AIPlayer("玩家1"),
        AIPlayer("玩家2"),
        AIPlayer("玩家3"),
        AIPlayer("玩家4")
    ]
    
    # 创建游戏实例
    game = MahjongGame(players)
    game.initialize_game()
    
    # 简单运行几轮
    round_count = 0
    max_rounds = 100
    
    print("游戏开始！")
    
    while not game.is_game_over and round_count < max_rounds:
        current_player = game.players[game.current_player_index]
        print(f"\n{current_player.name}的回合")
        
        # 摸牌
        drawn_tile = game.player_draw(game.current_player_index)
        print(f"摸牌: {drawn_tile}")
        
        # 检查自摸
        if check_hu(current_player.hand.tiles):
            print(f"{current_player.name} 自摸！")
            game.process_player_action(game.current_player_index, "hu", hu_type="自摸")
            break
        
        # AI决定操作
        action, params = current_player.decide_action(game.get_current_state())
        
        if action == "discard":
            print(f"打牌: {params['tile']}")
            game.process_player_action(game.current_player_index, action, **params)
        
        round_count += 1
    
    if game.is_game_over:
        print(f"\n游戏结束！胜利者: {game.winner.name}, 得分: {game.winner.score}")
    else:
        print("\n游戏达到最大回合数，结束。")


if __name__ == "__main__":
    run_game_example()